package com.eliza.library.utils.net

import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.engine.android.Android
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.get
import io.ktor.client.request.post
import io.ktor.client.statement.HttpResponse
import io.ktor.http.ContentType.Application.ProtoBuf
import io.ktor.http.HttpStatusCode
import io.ktor.http.URLBuilder
import io.ktor.http.path
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json
import javax.inject.Singleton

val httpClient = HttpClient(Android) {
//        install(Logging) {
//            logger = Logger.DEFAULT
//            level = LogLevel.HEADERS
//        }
//        JSON
    install(ContentNegotiation) {
        json(Json {
            ignoreUnknownKeys = true
            prettyPrint = true
            isLenient = true
        })
//        protobuf(ProtoBuf {
//            encodeDefaults = true
//        })
    }

}

data class HttpRequest(val path: String, val builder: HttpRequestBuilder.() -> Unit)

class HttpClient(val base: URLBuilder) {

    suspend inline fun <reified T> postx(
        path: String, block: HttpRequestBuilder.() -> Unit
    ): OptionResult<T> {
        base.path(path)
        val resp = httpClient.post(base.toString(), block)
        when (resp.status.value) {
            HttpStatusCode.OK.value -> return OptionResult.Success(resp.body<T>())
        }
        return OptionResult.Error(Exception(resp.toString()))
    }

    suspend inline fun <reified T> getx(
        path: String, block: HttpRequestBuilder.() -> Unit
    ): OptionResult<T> {
        base.path(path)
        val resp = httpClient.get(base.toString(), block)
        when (resp.status.value) {
            HttpStatusCode.OK.value -> return OptionResult.Success(resp.body<T>())
        }
        return OptionResult.Error(Exception(resp.toString()))
    }

    suspend inline fun post(
        path: String, block: HttpRequestBuilder.() -> Unit
    ): HttpResponse {
        base.path(path)
        println(base.toString())
        return httpClient.post(base.toString(), block)
    }

    suspend inline fun get(
        path: String, block: HttpRequestBuilder.() -> Unit
    ): HttpResponse {
        base.path(path)
        return httpClient.get(base.toString(), block)
    }

    companion object {
        suspend inline fun <reified T> postx(
            urlString: String, block: HttpRequestBuilder.() -> Unit
        ): OptionResult<T> {
            val resp = httpClient.post(urlString, block)
            when (resp.status.value) {
                HttpStatusCode.OK.value -> return OptionResult.Success(resp.body<T>())
            }
            return OptionResult.Error(Exception(resp.toString()))
        }

        suspend inline fun <reified T> getx(
            urlString: String, block: HttpRequestBuilder.() -> Unit
        ): OptionResult<T> {
            val resp = httpClient.get(urlString, block)
            when (resp.status.value) {
                HttpStatusCode.OK.value -> return OptionResult.Success(resp.body<T>())
            }
            return OptionResult.Error(Exception(resp.toString()))
        }

        suspend inline fun post(
            urlString: String, block: HttpRequestBuilder.() -> Unit
        ): HttpResponse {
            return httpClient.post(urlString, block)
        }

        suspend inline fun get(
            urlString: String, block: HttpRequestBuilder.() -> Unit
        ): HttpResponse {
            return httpClient.get(urlString, block)
        }
    }


}

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
    @Provides
    @Singleton
    fun provideHttpClient(): HttpClient {
        return httpClient
    }

    @Provides
    @Singleton
    fun provideCosmoService(): com.eliza.library.utils.net.HttpClient {
        val COSMO_BASE_URL = "https://cosmo-api.develop-sr3snxi-x6u2x52ooksf4.de-2.platformsh.site/"

        return HttpClient(URLBuilder(COSMO_BASE_URL))
    }

}
